package cn.edu.swu.miniwebsvr.core;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.io.OutputStream;
//服务器启动、监听请求、多线程/线程池管理。
//使用 ServerSocket 监听端口。使用 ExecutorService 线程池处理并发请求
public class Server {
    private final Config config = Config.getInstance();
    // 固定大小的线程池，用于处理并发客户端请求，这里初始化10个线程
    private final ExecutorService threadPool = Executors.newFixedThreadPool(10);

    /**
     * 启动服务器的入口方法
     * 功能：创建ServerSocket并监听指定端口，循环接收客户端连接，
     * 将每个连接封装为RequestProcessor任务提交到线程池处理
     */
    public void start() {
        // TODO: [学号/姓名] 实现 ServerSocket 的创建和监听
        // 使用try-with-resources创建ServerSocket，自动关闭资源
        try (ServerSocket serverSocket = new ServerSocket(config.getPort())) {
            System.out.println("MiniWebSvr 启动成功，监听端口：" + config.getPort());

            while (true) {
                // 阻塞等待客户端连接，获取客户端套接字
                Socket clientSocket = serverSocket.accept();
                System.out.println("接收到新的连接：" + clientSocket.getInetAddress());
                // 将客户端请求处理任务提交到线程池，由线程池分配线程执行
                threadPool.execute(new RequestProcessor(clientSocket));
            }
        } catch (IOException e) {
            System.err.println("服务器启动失败或运行异常: " + e.getMessage());
            threadPool.shutdown();
        }
    }
    /**
     * 请求处理内部类，实现Runnable接口，用于在线程池中处理单个客户端请求
     * 每个客户端连接对应一个该任务实例
     */
    private static class RequestProcessor implements Runnable {
        // 客户端套接字，用于与客户端通信（输入输出流）
        private final Socket socket;
        /**
         * 构造方法，初始化客户端套接字
         * @param socket 客户端连接的套接字对象
         */
        public RequestProcessor(Socket socket) {
            this.socket = socket;
        }
        /**
         * 线程执行的核心方法，处理客户端请求的具体逻辑
         * 流程：解析请求 -> 路由处理 -> 异常处理 -> 关闭资源
         */
        @Override
        public void run() {
            // TODO: [学号/姓名] 完善请求处理流程，确保异常安全和资源关闭
            try {
                // 1. 解析客户端输入流，获取请求参数（如请求方法、路径、参数等）
                Parameter request = HttpParser.parse(socket.getInputStream());
                // 2. 创建路由处理器，根据请求信息路由到对应的处理逻辑，并通过输出流响应客户端
                Router router = new Router();
                router.route(request, socket.getOutputStream());

            } catch (Exception e) {
                System.err.println("请求处理异常: " + e.getMessage());
                // TODO: [学号/姓名] 可以在这里实现返回 500 错误页面的逻辑
                try {
                    // 获取客户端输出流，用于发送错误响应
                    OutputStream out = socket.getOutputStream();

                    // 构造500错误的HTML响应体
                    String errorHtml = "<html>" +
                            "<head><title>500 Internal Server Error</title></head>" +
                            "<body>" +
                            "<h1>500 Internal Server Error</h1>" +
                            "<p>服务器内部错误，请稍后重试</p>" +
                            "</body></html>";

                    // 构造HTTP响应报文（遵循HTTP协议格式）
                    String response = "HTTP/1.1 500 Internal Server Error\r\n" +
                            "Content-Type: text/html; charset=UTF-8\r\n" +
                            "Content-Length: " + errorHtml.getBytes("UTF-8").length + "\r\n" +
                            "Connection: close\r\n" +  // 告知客户端处理后关闭连接
                            "\r\n" +  // 空行分隔响应头与响应体
                            errorHtml;

                    // 发送响应（使用UTF-8编码确保中文正常显示）
                    out.write(response.getBytes("UTF-8"));
                    out.flush();  // 强制刷新缓冲区，确保数据发送
                } catch (IOException e2) {
                    System.err.println("发送500错误响应失败: " + e2.getMessage());
                }
            } finally {
                try {
                    if (socket != null) socket.close();
                } catch (IOException e) { /* ignore */ }
            }
        }
    }
}
